home *** CD-ROM | disk | FTP | other *** search
- ;; -*- Mode:LISP; Package:(BOXER GLOBAL 1000); Base: 8.; Fonts: CPTFONT, CPTFONTB-*-
-
- #||
- Copyright 1985 Massachusetts Institute of Technology
-
- Permission to use, copy, modify, distribute, and sell this software
- and its documentation for any purpose is hereby granted without fee,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of M.I.T. not be used in
- advertising or publicity pertaining to distribution of the software
- without specific, written prior permission. M.I.T. makes no
- representations about the suitability of this software for any
- purpose. It is provided "as is" without express or implied warranty.
-
-
- +-Data--+
- This file is part of the | BOXER | system
- +-------+
-
- This file defines Boxer editor REGIONS
-
- A boxer region can have several different representations. The region object should be
- able to switch between these different representations easily. These representations are:
- A list of rows
- A REGION STREAM which is similar to a BOX stream except that there is no PLIST info.
- Two Boxer pointers (BP's) into existing editor stucture.
-
- In general, only one representation will be relevant at a given time. For example, while
- the user sets up the region in the editor, we use the BP representation.
- If the region is Killed, then we need to store the killed region as a list of rows.
- Copying regions will probably use streams
-
- Regions are also responsible for updating their own redisplay
- In many cases, this will probably involve allocating and deallocating several groups
- of rectangular blinkers since there could be several screen objects for each row in the
- region. (Mark them all or just where we are ??)
-
- Note, We call them EDITOR-REGIONs for now to avoid naming problems with the already existing
- flavor called REGION which is used in the redisplay
-
- Each Box is capable of having its own Region. When the Box is FUNCALLed, only the
- contents of the Box which are in the Region will be seen by the Evaluator.
-
- ||#
-
- (DEFMETHOD (EDITOR-REGION :ROWS) ()
- ROWS)
-
- (DEFMETHOD (EDITOR-REGION :BLINKER-LIST) ()
- BLINKER-LIST)
-
- (DEFMETHOD (EDITOR-REGION :START-BP) ()
- START-BP)
-
- (DEFMETHOD (EDITOR-REGION :STOP-BP) ()
- STOP-BP)
-
- (DEFMETHOD (EDITOR-REGION :SET-START-BP) (NEW-START)
- (CHECK-BP-ARG NEW-START)
- (SETQ START-BP NEW-START))
-
- (DEFMETHOD (EDITOR-REGION :SET-STOP-BP) (NEW-STOP)
- (CHECK-BP-ARG NEW-STOP)
- (SETQ STOP-BP NEW-STOP))
-
- (DEFUN MAKE-EDITOR-REGION (START-BP &OPTIONAL (STOP-BP *POINT*))
- (IF (AND (BP? START-BP) (BP? STOP-BP))
- (MAKE-INSTANCE 'EDITOR-REGION ':START-BP START-BP ':STOP-BP STOP-BP)
- (FERROR "One or both of the args: ~S, ~S was not a Boxer pointer" START-BP STOP-BP)))
-
- ;;; This returns a list of ROWS of the lowest common superior box of the two BP's. The list
- ;;; is ordered from top to bottom. The method also returns start and stop BP's which
- ;;; correspond to the rows which are returned (not neccessarily where the BP's are located)
- ;;; The returned BP's are also guaranteed to be "ordered" from top to bottom AND
- ;;; from left to right (if they are on the same line that is)
-
- (DEFMETHOD (EDITOR-REGION :GET-ROWS-FROM-BPS) ()
- (UNLESS (OR (NULL START-BP) (NULL STOP-BP))
- (MULTIPLE-VALUE-BIND (TL-START-BP TL-STOP-BP) ;bind the "top-level" BPs
- (ORDER-BPS START-BP STOP-BP)
- (LOOP FOR CURRENT-ROW = (BP-ROW TL-START-BP) THEN (TELL CURRENT-ROW :NEXT-ROW)
- COLLECT CURRENT-ROW INTO RETURN-ROWS
- UNTIL (EQ CURRENT-ROW (BP-ROW TL-STOP-BP))
- FINALLY
- (RETURN (VALUES RETURN-ROWS TL-START-BP TL-STOP-BP))))))
-
- ;;; If you want to use all the values returned by the :GET-ROWS-FORM-BPS message
- ;;; then use this macro instead since it performs cleanup on the rows with the newly
- ;;; created BPs
-
- (DEFMACRO WITH-REGION-ROWS-AND-BPS-BOUND ((EDITOR-REGION) &BODY BODY)
- "Creates and environment with REGION-ROWS bound to the rows of the EDITOR-REGION and
- REGION-START-BP and REGION-STOP-BP bound to BPs which are at the same level and ordered.
- Then cleans up afterwards. "
- `(MULTIPLE-VALUE-BIND (REGION-ROWS REGION-START-BP REGION-STOP-BP)
- (TELL ,EDITOR-REGION :GET-ROWS-FROM-BPS)
- (UNWIND-PROTECT
- (PROGN . ,BODY)
- (TELL (BP-ROW REGION-START-BP) :DELETE-BP REGION-START-BP)
- (TELL (BP-ROW REGION-STOP-BP) :DELETE-BP REGION-STOP-BP))))
-
- (DEFMACRO WITH-REGION-TOP-LEVEL-BPS-BOUND ((EDITOR-REGION) &BODY BODY)
- "Creates and environment with REGION-START-BP and REGION-STOP-BP bound to BPs which are at
- the same level and ordered. Then cleans up afterwards. "
- `(MULTIPLE-VALUE-BIND (REGION-START-BP REGION-STOP-BP)
- (ORDER-BPS (TELL ,EDITOR-REGION :START-BP) (TELL ,EDITOR-REGION :STOP-BP))
- (UNWIND-PROTECT
- (PROGN . ,BODY)
- (TELL (BP-ROW REGION-START-BP) :DELETE-BP REGION-START-BP)
- (TELL (BP-ROW REGION-STOP-BP) :DELETE-BP REGION-STOP-BP))))
-
- (DEFMETHOD (EDITOR-REGION :SET-ROWS) (ROWS-TO-SET)
- ;; this converts the region's internal representation to rows ONLY.
- (TELL SELF :MAKE-INVISIBLE)
- ;; First we clean up any displayed blinkers that may exist
- (DOLIST (BLINKER BLINKER-LIST)
- (REMOVE-REGION-ROW-BLINKER BLINKER))
- (SETQ BLINKER-LIST NIL)
- ;; Then we get rid of the BP's since the region should probably NOT have any thing to do
- ;; with REAL structure if we are sending this message to it
- (SETQ START-BP NIL STOP-BP NIL)
- ;; Finally, we set the rows to what they want to be
- (SETQ ROWS ROWS-TO-SET))
-
- (DEFMETHOD (EDITOR-REGION :COPY) ()
- (LET ((NEW-REGION (MAKE-INSTANCE 'EDITOR-REGION)))
- (TELL NEW-REGION :SET-ROWS (MAPCAR #'COPY-ROW ROWS))
- NEW-REGION))
-
- (DEFMETHOD (EDITOR-REGION :SET-BPS) (BP1 BP2)
- ;; this converts the region's internal representation to BP's ONLY.
- ;; first, clear out the rows
- (SETQ ROWS NIL)
- ;; now set the BP's
- (SETQ START-BP BP1 STOP-BP BP2))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; INTERACTIONS BETWEEN REGIONS AND BOXES ;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (DEFMETHOD (BOX :GET-REGION-CHECK-SUPERIORS) ()
- (LET ((SUPERIOR-BOX (TELL SELF :SUPERIOR-BOX)))
- (COND ((EDITOR-REGION? REGION) REGION)
- ((BOX? SUPERIOR-BOX) (TELL SUPERIOR-BOX :GET-REGION-CHECK-SUPERIORS))
- (T NIL))))
-
- (DEFMETHOD (EDITOR-REGION :BOX) ()
- BOX)
-
- (DEFMETHOD (EDITOR-REGION :SET-BOX) (NEW-BOX)
- (SETQ BOX NEW-BOX))
-
- (DEFMETHOD (BOX :REGION) ()
- REGION)
-
- (DEFMETHOD (BOX :SET-REGION) (NEW-REGION)
- (SETQ REGION NEW-REGION)
- (TELL SELF :MODIFIED T)) ;flush the code cache
-
- ;; Use this one from the outside since at some point in the future, we may allow more than
- ;; one region in a BOX or ONLY one region in ALL of BOXER
- ;; No matter what, this is guaranteed to get you whatever the most appropriate region is if
- ;; it exists
-
- (DEFUN GET-CURRENT-REGION ()
- (TELL (POINT-BOX) :GET-REGION-CHECK-SUPERIORS))
-
- (DEFUN GET-LOCAL-REGION (&OPTIONAL (BP *POINT*))
- (TELL (BP-BOX BP) :REGION))
-
- (DEFUN INSTALL-REGION (REGION &OPTIONAL (BP *POINT*))
- (TELL REGION :SET-BOX (BP-BOX BP))
- (TELL (BP-BOX BP) :SET-REGION REGION)
- (COND-EVERY ((EQ REGION *REGION-BEING-DEFINED*)
- (SETQ *REGION-BEING-DEFINED* NIL))
- ((EQ REGION *FOLLOWING-MOUSE-REGION*)
- (SETQ *FOLLOWING-MOUSE-REGION* NIL))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; TOP LEVEL REGION MANIPULATING COMMANDS ;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
-
- (DEFUN FLUSH-REGION (REGION)
- (WHEN (NOT-NULL REGION)
- (TELL REGION :MAKE-INVISIBLE)
- (TELL-CHECK-NIL (TELL REGION :BOX) :SET-REGION NIL)
- (DOLIST (BLINKER (TELL REGION :BLINKER-LIST))
- (REMOVE-REGION-ROW-BLINKER BLINKER))
- (SETQ REGION-LIST (DELQ REGION REGION-LIST))
- (COND-EVERY ((EQ REGION *REGION-BEING-DEFINED*)
- (SETQ *REGION-BEING-DEFINED* NIL))
- ((EQ REGION *FOLLOWING-MOUSE-REGION*)
- (SETQ *FOLLOWING-MOUSE-REGION* NIL)))))
-
- ;;; As long as we keep the *POINT* and the *CURRENT-EDITOR-REGION* coupled...
- (DEFUN BP-IN-REGION? (BP REGION-ROWS)
- BP REGION-ROWS
- T)
-
- (DEFUN KILL-REGION (REGION)
- (WITH-REGION-ROWS-AND-BPS-BOUND (REGION)
- (LET* ((FIRST-ROW (CAR REGION-ROWS))
- (LAST-ROW (CAR (LAST REGION-ROWS)))
- (REGION-BOX (TELL FIRST-ROW :SUPERIOR-BOX))
- (MIDDLE-ROWS (BUTLAST (CDR REGION-ROWS)))
- (FIRST-CHA-NO (BP-CHA-NO REGION-START-BP))
- (LAST-CHA-NO (BP-CHA-NO REGION-STOP-BP)))
- (COND ((EQ FIRST-ROW LAST-ROW)
- (TELL REGION
- :SET-ROWS
- (LIST (TELL FIRST-ROW
- :DELETE-CHAS-BETWEEN-CHA-NOS FIRST-CHA-NO LAST-CHA-NO))))
- (T
- (TELL REGION
- :SET-ROWS
- (APPEND
- (NCONS (TELL FIRST-ROW :KILL-CHAS-AT-CHA-NO FIRST-CHA-NO))
- MIDDLE-ROWS
- (NCONS (TELL LAST-ROW
- :DELETE-CHAS-BETWEEN-CHA-NOS 0 LAST-CHA-NO))))
- (UNLESS (NULL MIDDLE-ROWS)
- (TELL REGION-BOX :DELETE-BETWEEN-ROWS (CAR MIDDLE-ROWS)
- (CAR (LAST MIDDLE-ROWS))))
- (TELL FIRST-ROW :INSERT-ROW-CHAS-AT-CHA-NO LAST-ROW FIRST-CHA-NO)
- (TELL REGION-BOX :DELETE-ROW LAST-ROW)))
- ;;; Clean up time
- (WHEN (BP-IN-REGION? *POINT* REGION-ROWS)
- (LET ((REGION-SCREEN-BOX (OR (TELL-CHECK-NIL (CURRENT-SCREEN-ROW FIRST-ROW)
- :SCREEN-BOX)
- (TELL (CAR (MEM #'(LAMBDA (BOX ROW)
- (TELL BOX :SUPERIOR? ROW))
- (BP-SCREEN-BOX *POINT*)
- (LOOP FOR ROW IN REGION-ROWS
- APPEND
- (TELL ROW
- :DISPLAYED-SCREEN-OBJS))))
- :SCREEN-BOX))))
- (MOVE-POINT-1 FIRST-ROW FIRST-CHA-NO REGION-SCREEN-BOX))))))
-
- (DEFUN YANK-REGION (BP REGION &OPTIONAL (FORCE-BP-TYPE ':MOVING)
- &AUX (NEW-START-BP (MAKE-BP ':FIXED))
- (NEW-STOP-BP (MAKE-BP ':FIXED)))
- (ACTION-AT-BP-INTERNAL
- (LET* ((BOX (BP-BOX BP))
- (ROW (BP-ROW BP))
- (CHA-NO (BP-CHA-NO BP))
- (REMAINS (TELL ROW :KILL-CHAS-AT-CHA-NO CHA-NO))
- (FIRST-NEW-ROW (CAR (TELL REGION :ROWS)))
- (REST-NEW-ROWS (CDR (TELL REGION :ROWS)))
- (LAST-NEW-ROW (CAR (LAST REST-NEW-ROWS))))
- ;;remember where we are
- (MOVE-BP NEW-START-BP (BP-VALUES BP))
- ;; add the region
- (TELL ROW :INSERT-ROW-CHAS-AT-CHA-NO FIRST-NEW-ROW CHA-NO)
- (IF (NULL REST-NEW-ROWS)
- (TELL ROW :INSERT-ROW-CHAS-AT-CHA-NO REMAINS (TELL ROW :LENGTH-IN-CHAS))
- (LOOP FOR NEW-ROW IN REST-NEW-ROWS
- FOR CURRENT-ROW = ROW THEN (TELL CURRENT-ROW :NEXT-ROW)
- DO (TELL BOX :INSERT-ROW-AFTER-ROW NEW-ROW CURRENT-ROW)
- FINALLY (TELL LAST-NEW-ROW
- :INSERT-ROW-CHAS-AT-CHA-NO REMAINS
- (TELL LAST-NEW-ROW :LENGTH-IN-CHAS))))
- ;; now remember where we stopped
- (MOVE-BP NEW-STOP-BP (BP-VALUES BP))
- ;; now tell the region about it
- (TELL REGION :SET-BPS NEW-START-BP NEW-STOP-BP))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; Redisplay of REGIONS ;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; Regions are displayed as one or more blinkers. With Each blinker corresponding to screen
- ;;; representation(s) for the rows which make up the region
-
- (DEFUN MAKE-REGION-ROW-BLINKER (SCREEN-ROW)
- (LET ((NEW-BLINKER (TV:MAKE-BLINKER *BOXER-PANE* 'REGION-ROW-BLINKER
- ':VISIBILITY NIL ':FOLLOW-P NIL)))
- (SETF (REGION-ROW-BLINKER-UID NEW-BLINKER) SCREEN-ROW)
- NEW-BLINKER))
-
- (DEFMETHOD (EDITOR-REGION :TURN-ON) ()
- (UNLESS VISIBILITY
- (TELL SELF :MAKE-VISIBLE))
- (SETQ VISIBILITY T))
-
- (DEFMETHOD (EDITOR-REGION :TURN-OFF) ()
- (WHEN VISIBILITY
- (TELL SELF :MAKE-INVISIBLE))
- (SETQ VISIBILITY NIL))
-
- ;;; We provide two different messages for redisplay of regions. One of them will just mark
- ;;; the screen rows corresponding to the region in the *CURRENT-SCREEN-BOX* while the other
- ;;; one will mark *ALL* the screen rows of the region.
- (DEFUN REMOVE-REGION-ROW-BLINKER (ROW-BLINKER)
- (ALTERING-REGION (ROW-BLINKER)
- (SETF (TV:SHEET-BLINKER-LIST *BOXER-PANE*)
- (DELQ ROW-BLINKER (TV:SHEET-BLINKER-LIST *BOXER-PANE*)))))
-
- (DEFUN UPDATE-ROW-BLINKER-LIST (ROW-BLINKERS SCREEN-ROWS)
- "A blinker for every row and no extra blinkers. Returns a list of blinkers"
- (LOOP FOR SCREEN-ROW IN SCREEN-ROWS
- COLLECT (LET ((EXISTING-REGION
- (CAR (MEM #'(LAMBDA (UID REG) (EQ UID (REGION-ROW-BLINKER-UID REG)))
- SCREEN-ROW ROW-BLINKERS))))
- (IF (NULL EXISTING-REGION)
- (MAKE-REGION-ROW-BLINKER SCREEN-ROW)
- (SETQ ROW-BLINKERS (DELQ EXISTING-REGION ROW-BLINKERS))
- EXISTING-REGION))
- INTO NEW-LIST
- FINALLY (PROGN (DOLIST (OLD-BLINKER ROW-BLINKERS)
- (REMOVE-REGION-ROW-BLINKER OLD-BLINKER))
- (RETURN NEW-LIST))))
-
- ;;; Accessor Macros...
- (DEFSUBST REGION-ROW-BLINKER-WID (REGION)
- (SYMEVAL-IN-INSTANCE REGION 'TV:WIDTH))
-
- (DEFSUBST REGION-ROW-BLINKER-HEI (REGION)
- (SYMEVAL-IN-INSTANCE REGION 'TV:HEIGHT))
-
- (DEFSUBST REGION-ROW-BLINKER-X (REGION)
- (TV:BLINKER-X-POS REGION))
-
- (DEFSUBST REGION-ROW-BLINKER-Y (REGION)
- (TV:BLINKER-Y-POS REGION))
-
- ;; Blinkers positions are with respect to the window WITH THE BORDERS INCLUDED
- (DEFMACRO FIXUP-COORDINATES-FOR-BLINKER (X Y BL)
- `(LET ((SHEET (SEND ,BL :SHEET)))
- (SETF ,X (+ ,X (SEND SHEET :LEFT-MARGIN-SIZE)))
- (SETF ,Y (+ ,Y (SEND SHEET :TOP-MARGIN-SIZE)))))
-
- (DEFUN UPDATE-REGION-ROW-BLINKER (REGION-ROW-BLINKER)
- (LET* ((SCREEN-ROW (REGION-ROW-BLINKER-UID REGION-ROW-BLINKER))
- (WID (SCREEN-OBJ-WID SCREEN-ROW))
- (HEI (SCREEN-OBJ-HEI SCREEN-ROW)))
- (MULTIPLE-VALUE-BIND (X Y)
- (TELL SCREEN-ROW :POSITION)
- ;; Blinker positions are measured with the borders included
- (FIXUP-COORDINATES-FOR-BLINKER X Y REGION-ROW-BLINKER)
- (WHEN (OR ( WID (REGION-ROW-BLINKER-WID REGION-ROW-BLINKER))
- ( HEI (REGION-ROW-BLINKER-HEI REGION-ROW-BLINKER))
- ( X (REGION-ROW-BLINKER-X REGION-ROW-BLINKER))
- ( Y (REGION-ROW-BLINKER-Y REGION-ROW-BLINKER)))
- ;; might be better to use timestamps (we might have to use timestamps in addition)
- (ALTERING-REGION (REGION-ROW-BLINKER)
- (SETF (REGION-ROW-BLINKER-WID REGION-ROW-BLINKER) WID)
- (SETF (REGION-ROW-BLINKER-HEI REGION-ROW-BLINKER) HEI)
- (SETF (REGION-ROW-BLINKER-X REGION-ROW-BLINKER) X)
- (SETF (REGION-ROW-BLINKER-Y REGION-ROW-BLINKER) Y))))))
-
- (DEFUN LEFT-HALF-BLINKER-TRIM (BLINKER CHA-NO)
- (LET* ((SCREEN-ROW (REGION-ROW-BLINKER-UID BLINKER))
- (SCREEN-CHAS (TELL SCREEN-ROW :SCREEN-CHAS))
- (ROW-WID (TELL SCREEN-ROW :WID))
- (ROW-HEI (TELL SCREEN-ROW :HEI))
- (AMOUNT-TO-TRIM (LOOP FOR INDEX FROM 0 BELOW CHA-NO
- FOR CHA IN SCREEN-CHAS
- SUMMING (IF (SCREEN-CHA? CHA)
- (CHA-WID (FONT-NO CHA) (CHA-CODE CHA))
- (SCREEN-OBJ-WID CHA))))
- (DESIRED-WID (- ROW-WID AMOUNT-TO-TRIM)))
- (MULTIPLE-VALUE-BIND (X Y)
- (TELL SCREEN-ROW :POSITION)
- ;; Blinker positions are measured with the borders included
- (FIXUP-COORDINATES-FOR-BLINKER X Y BLINKER)
- (WHEN (OR ( DESIRED-WID (REGION-ROW-BLINKER-WID BLINKER))
- ( ROW-HEI (REGION-ROW-BLINKER-HEI BLINKER))
- ( (+ X AMOUNT-TO-TRIM) (REGION-ROW-BLINKER-X BLINKER))
- ( Y (REGION-ROW-BLINKER-Y BLINKER)))
- (ALTERING-REGION (BLINKER)
- (SETF (REGION-ROW-BLINKER-WID BLINKER) DESIRED-WID)
- (SETF (REGION-ROW-BLINKER-HEI BLINKER) ROW-HEI)
- (SETF (REGION-ROW-BLINKER-X BLINKER) (+ X AMOUNT-TO-TRIM))
- (SETF (REGION-ROW-BLINKER-Y BLINKER) Y))))))
-
- (DEFUN RIGHT-HALF-BLINKER-TRIM (BLINKER CHA-NO)
- (LET* ((SCREEN-ROW (REGION-ROW-BLINKER-UID BLINKER))
- (SCREEN-CHAS (TELL SCREEN-ROW :SCREEN-CHAS))
- (ROW-WID (TELL SCREEN-ROW :WID))
- (ROW-HEI (TELL SCREEN-ROW :HEI))
- (AMOUNT-TO-TRIM (IF ( CHA-NO (TELL SCREEN-ROW :LENGTH))
- 0
- (LOOP FOR CHA IN (NTHCDR CHA-NO SCREEN-CHAS)
- SUMMING (IF (SCREEN-CHA? CHA)
- (CHA-WID (FONT-NO CHA) (CHA-CODE CHA))
- (SCREEN-OBJ-WID CHA)))))
- (DESIRED-WID (- ROW-WID AMOUNT-TO-TRIM)))
- (MULTIPLE-VALUE-BIND (X Y)
- (TELL SCREEN-ROW :POSITION)
- ;; Blinker positions are measured with the borders included
- (FIXUP-COORDINATES-FOR-BLINKER X Y BLINKER)
- (WHEN (OR ( DESIRED-WID (REGION-ROW-BLINKER-WID BLINKER))
- ( ROW-HEI (REGION-ROW-BLINKER-HEI BLINKER))
- ( X (REGION-ROW-BLINKER-X BLINKER))
- ( Y (REGION-ROW-BLINKER-Y BLINKER)))
- (ALTERING-REGION (BLINKER)
- (SETF (REGION-ROW-BLINKER-WID BLINKER) DESIRED-WID)
- (SETF (REGION-ROW-BLINKER-HEI BLINKER) ROW-HEI)
- (SETF (REGION-ROW-BLINKER-X BLINKER) X)
- (SETF (REGION-ROW-BLINKER-Y BLINKER) Y))))))
-
- (DEFUN BOTH-ENDS-BLINKER-TRIM (BLINKER START-CHA-NO STOP-CHA-NO)
- (LET* ((SCREEN-ROW (REGION-ROW-BLINKER-UID BLINKER))
- (SCREEN-CHAS (TELL SCREEN-ROW :SCREEN-CHAS))
- (ROW-WID (TELL SCREEN-ROW :WID))
- (ROW-HEI (TELL SCREEN-ROW :HEI))
- (LEFT-TRIM (LOOP FOR INDEX FROM 0 BELOW START-CHA-NO
- FOR CHA IN SCREEN-CHAS
- SUMMING (IF (SCREEN-CHA? CHA)
- (CHA-WID (FONT-NO CHA) (CHA-CODE CHA))
- (SCREEN-OBJ-WID CHA))))
- (RIGHT-TRIM (IF ( STOP-CHA-NO (TELL SCREEN-ROW :LENGTH))
- 0
- (LOOP FOR CHA IN (NTHCDR STOP-CHA-NO SCREEN-CHAS)
- SUMMING (IF (SCREEN-CHA? CHA)
- (CHA-WID (FONT-NO CHA) (CHA-CODE CHA))
- (SCREEN-OBJ-WID CHA)))))
- (DESIRED-WID (- ROW-WID LEFT-TRIM RIGHT-TRIM)))
- (MULTIPLE-VALUE-BIND (X Y)
- (TELL SCREEN-ROW :POSITION)
- ;; Blinker positions are measured with the borders included
- (FIXUP-COORDINATES-FOR-BLINKER X Y BLINKER)
- (WHEN (OR ( DESIRED-WID (REGION-ROW-BLINKER-WID BLINKER))
- ( ROW-HEI (REGION-ROW-BLINKER-HEI BLINKER))
- ( (+ X LEFT-TRIM) (REGION-ROW-BLINKER-X BLINKER))
- ( Y (REGION-ROW-BLINKER-Y BLINKER)))
- (ALTERING-REGION (BLINKER)
- (SETF (REGION-ROW-BLINKER-WID BLINKER) DESIRED-WID)
- (SETF (REGION-ROW-BLINKER-HEI BLINKER) ROW-HEI)
- (SETF (REGION-ROW-BLINKER-X BLINKER) (+ X LEFT-TRIM))
- (SETF (REGION-ROW-BLINKER-Y BLINKER) Y))))))
-
- (DEFMETHOD (EDITOR-REGION :UPDATE-REDISPLAY-ALL-ROWS) ()
- (WITH-FONT-MAP-BOUND (*BOXER-PANE*)
- ;; we have to bind this because region redisplay can be called OUTSIDE of normal redisplay
- (COND ((OR (NULL START-BP) (NULL STOP-BP))
- ;; No BP's mean that there is not any screen structure. Probably a region got wiped
- (DOLIST (BLINKER BLINKER-LIST)
- (REMOVE-REGION-ROW-BLINKER BLINKER))
- (SETQ BLINKER-LIST NIL))
- (T
- (WITH-REGION-ROWS-AND-BPS-BOUND (SELF)
- ;; First we do "allocation" that is, make sure that there is a blinker for every
- ;; screen row and vice versa. Note that blinker list will be ordered from top
- ;; to bottom
- (SETQ BLINKER-LIST
- (UPDATE-ROW-BLINKER-LIST BLINKER-LIST
- (LOOP FOR ROW IN REGION-ROWS
- APPEND
- (TELL ROW :DISPLAYED-SCREEN-OBJS))))
- (IF VISIBILITY (TELL SELF :MAKE-VISIBLE) (TELL SELF :MAKE-INVISIBLE))
- (LET ((STARTING-ROW (BP-ROW REGION-START-BP))
- (STARTING-CHA-NO (BP-CHA-NO REGION-START-BP))
- (STOPPING-ROW (BP-ROW REGION-STOP-BP))
- (STOPPING-CHA-NO (BP-CHA-NO REGION-STOP-BP)))
- (LOOP FOR BLINKER IN BLINKER-LIST
- FOR BLINKER-ROW = (REGION-ROW-BLINKER-UID BLINKER)
- DOING
- (COND ((AND (EQ STARTING-ROW (TELL BLINKER-ROW :ACTUAL-OBJ))
- (EQ STOPPING-ROW (TELL BLINKER-ROW :ACTUAL-OBJ)))
- ;; the row is both the first and last one in a region so we should
- ;; trim both ends of it
- (BOTH-ENDS-BLINKER-TRIM BLINKER STARTING-CHA-NO STOPPING-CHA-NO))
- ((EQ STARTING-ROW (TELL BLINKER-ROW :ACTUAL-OBJ))
- ;; If the row is the first one in a region then it needs to be
- ;; trimmed to correspond to where the BP is pointing
- (LEFT-HALF-BLINKER-TRIM BLINKER STARTING-CHA-NO))
- ((EQ STOPPING-ROW (TELL BLINKER-ROW :ACTUAL-OBJ))
- ;; If the row is the last one in the region, then it ALSO needs
- ;; to be trimmed to correspond to where the BP is pointing
- (RIGHT-HALF-BLINKER-TRIM BLINKER STOPPING-CHA-NO))
- (T
- ;; finally, take care of all the other rows
- (UPDATE-REGION-ROW-BLINKER BLINKER))))))))))
-
- (DEFMETHOD (EDITOR-REGION :UPDATE-REDISPLAY-CURRENT-ROWS) ()
- (WITH-FONT-MAP-BOUND (*BOXER-PANE*)
- (COND ((OR (NULL START-BP) (NULL STOP-BP))
- ;; No BP's mean that there is not any screen structure. Probably a region got wiped
- (DOLIST (BLINKER BLINKER-LIST)
- (REMOVE-REGION-ROW-BLINKER BLINKER))
- (SETQ BLINKER-LIST NIL))
- (T
- (WITH-REGION-ROWS-AND-BPS-BOUND (SELF)
- ;; First we do "allocation" that is, make sure that there is a blinker for every
- ;; screen row and vice versa. Note that blinker list will be ordered from top
- ;; to bottom
- (SETQ BLINKER-LIST
- (UPDATE-ROW-BLINKER-LIST BLINKER-LIST
- (LOOP FOR ROW IN REGION-ROWS
- COLLECT (CURRENT-SCREEN-ROW ROW))))
- (IF VISIBILITY (TELL SELF :MAKE-VISIBLE) (TELL SELF :MAKE-INVISIBLE))
- (LET ((STARTING-ROW (BP-ROW REGION-START-BP))
- (STARTING-CHA-NO (BP-CHA-NO REGION-START-BP))
- (STOPPING-ROW (BP-ROW REGION-STOP-BP))
- (STOPPING-CHA-NO (BP-CHA-NO REGION-STOP-BP)))
- (LOOP FOR BLINKER IN BLINKER-LIST
- FOR BLINKER-ROW = (REGION-ROW-BLINKER-UID BLINKER)
- DOING
- (COND ((AND (EQ STARTING-ROW (TELL BLINKER-ROW :ACTUAL-OBJ))
- (EQ STARTING-ROW (TELL BLINKER-ROW :ACTUAL-OBJ)))
- ;; the row is both the first and last one in a region so we should
- ;; trim both ends of it
- (BOTH-ENDS-BLINKER-TRIM BLINKER STARTING-CHA-NO STOPPING-CHA-NO))
- ((EQ STARTING-ROW (TELL BLINKER-ROW :ACTUAL-OBJ))
- ;; If the row is the first one in a region then it needs to be
- ;; trimmed to correspond to where the BP is pointing
- (LEFT-HALF-BLINKER-TRIM BLINKER STARTING-CHA-NO))
- ((EQ STOPPING-ROW (TELL BLINKER-ROW :ACTUAL-OBJ))
- ;; If the row is the last one in the region, then it ALSO needs
- ;; to be trimmed to correspond to where the BP is pointing
- (RIGHT-HALF-BLINKER-TRIM BLINKER STOPPING-CHA-NO))
- (T
- ;; finally, take care of all the other rows
- (UPDATE-REGION-ROW-BLINKER BLINKER))))))))))
-
- (DEFMETHOD (EDITOR-REGION :MAKE-VISIBLE) ()
- (DOLIST (ROW-BLINKER BLINKER-LIST)
- (TELL ROW-BLINKER :SET-VISIBILITY T)))
-
- (DEFMETHOD (EDITOR-REGION :MAKE-INVISIBLE) ()
- (DOLIST (ROW-BLINKER BLINKER-LIST)
- (TELL ROW-BLINKER :SET-VISIBILITY NIL)))
-
-
-
-